<template>
  <div>
    <!-- 面包屑导航区 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>商品列表</el-breadcrumb-item>
    </el-breadcrumb>

    <!-- 卡片视图区域 -->
    <el-card>
      <el-row :gutter="20">
        <el-col :span="8">
          <el-input
            placeholder="请输入商品名称（模糊搜索）"
            v-model="queryInfo.query"
          >
            <el-button
              slot="append"
              icon="el-icon-search"
              @click="handlesearchGoods"
            ></el-button> </el-input
        ></el-col>
      </el-row>

      <!-- table表格 -->
      <el-table :data="goodsList" border stripe>
        <!-- <el-table-column type="expand">
          <template slot-scope="scope">
            <el-descriptions title="其他信息" border style="padding: 10px">
              <el-descriptions-item label="商品描述">{{
                scope.row.description
              }}</el-descriptions-item>

            </el-descriptions>
          </template>
        </el-table-column> -->
        <el-table-column prop="id" width="60px"> </el-table-column>
        <el-table-column prop="cover_url" label="封面图片" width="140px">
          <template slot-scope="scope">
            <!-- <el-image :src="domain + scope.row.cover_url"></el-image> -->
            <el-image :src="scope.row.cover_url"></el-image>
          </template>
        </el-table-column>
        <el-table-column prop="name" label="商品名称"> </el-table-column>
        <el-table-column prop="description" label="商品描述" width="250px">
        </el-table-column>
        <el-table-column prop="count" label="商品库存" width="95px">
        </el-table-column>
        <el-table-column prop="is_deleted" label="状态" width="80px">
          <template slot-scope="scope">
            <el-tooltip
              class="item"
              effect="dark"
              :content="scope.row.delete_time | dateFormat"
              placement="top"
            >
              <el-tag v-if="scope.row.delete_time != ''" type="danger"
                >被删除</el-tag
              >
              <el-tag v-else type="info">正常</el-tag>
            </el-tooltip>
          </template>
        </el-table-column>

        <el-table-column label="操作" width="500px">
          <template slot-scope="scope">
            <!-- 显示/修改信息 -->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="min"
              @click="handleShowGoodsDialog(scope.row)"
              >商品</el-button
            >

            <!-- 显示/修改参数 -->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="min"
              @click="handleShowParamDialog(scope.row.id)"
              >参数</el-button
            >

            <!-- 显示/修改商品详细信息 -->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="min"
              @click="handleShowDetailsDialog(scope.row.id)"
              >详细</el-button
            >

            <!-- 显示/修改商品轮播图 -->
            <el-button
              type="primary"
              icon="el-icon-edit"
              size="min"
              @click="handleShowSwiperDialog(scope.row.id)"
              >图片</el-button
            >

            <el-button
              type="danger"
              icon="el-icon-delete"
              size="min"
              @click="handleDeleteGoods(scope.row.id)"
            ></el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <el-pagination
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="queryInfo.pageNum"
        :page-size="queryInfo.pageSize"
        :page-sizes="[3, 5, 10, 20]"
        layout="total, sizes,prev, pager, next,jumper"
        :total="total"
      >
      </el-pagination>
    </el-card>

    <!-- 参数 -->
    <el-dialog
      title="商品参数信息"
      :visible.sync="paramDialog"
      width="35%"
      @close="currParamList = []"
    >
      <div class="param-wrapper">
        <el-tag
          :key="param.id"
          v-for="param in currParamList"
          style="cursor: pointer"
          closable
          effect="dark"
          :disable-transitions="true"
          :type="param.is_empty ? 'danger' : ''"
          @click="handleShowEditParamDialog(param, true)"
          @close="handleDeleteParam(param.id, param.goods_id)"
        >
          {{ param.name + ' （价格：' + param.price + ' 元） ' }}
        </el-tag>
      </div>

      <span slot="footer" class="dialog-footer">
        <el-button
          type="primary"
          @click="handleShowEditParamDialog(param, false, currGoodsId)"
          >添 加 参 数</el-button
        >
        <el-button type="primary" @click="paramDialog = false">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改参数 -->
    <el-dialog
      :title="isEditParams ? '修改' : '添加' + '参数信息'"
      :visible.sync="editParamDialog"
      @close="handleCloseEditParam"
      width="40%"
    >
      <el-form
        label-width="80px"
        :model="paramsFormData"
        :rules="paramsFormRules"
        ref="paramsFormRef"
      >
        <el-form-item label="商品id">
          <el-input v-model="paramsFormData.goods_id" disabled></el-input>
        </el-form-item>
        <el-form-item label="id">
          <el-input v-model="paramsFormData.id" disabled></el-input>
        </el-form-item>

        <el-form-item label="参数名称">
          <el-input v-model="paramsFormData.name"></el-input>
        </el-form-item>

        <el-form-item label="价格">
          <el-input v-model="paramsFormData.price" type="number"></el-input>
        </el-form-item>

        <el-form-item label="是否无货">
          <el-switch
            v-model="paramsFormData.is_empty"
            active-text="是"
            inactive-text="否"
          >
          </el-switch>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editParamDialog = false"
          >取 消</el-button
        >
        <el-button type="primary" @click="handleUpdateParams">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改商品基本信息 -->
    <el-dialog
      title="修改商品基本信息"
      :visible.sync="editGoodsDialog"
      @close="handleCloseEditGoods"
      width="40%"
    >
      <el-form
        label-width="80px"
        :model="editGoodsForm"
        :rules="editGoodsFormRules"
        ref="goodsFormRef"
      >
        <el-form-item label="id">
          <el-input v-model="editGoodsForm.id" disabled></el-input>
        </el-form-item>
        <el-form-item label="商品照片" prop="cover">
          <el-upload
            class="avatar-uploader"
            :show-file-list="false"
            action="#"
            ref="upload"
            :http-request="handleUploadCover"
          >
            <img :src="editGoodsForm.cover.url" class="avatar" />
          </el-upload>
          <span class="tips">（建议尺寸 1：1，点击图片重新上传）</span>
        </el-form-item>
        <el-form-item label="商品名称" prop="name">
          <el-input v-model="editGoodsForm.name"></el-input>
        </el-form-item>
        <el-form-item label="商品描述" prop="description">
          <el-input v-model="editGoodsForm.description"></el-input>
        </el-form-item>

        <el-form-item label="商品库存" prop="count">
          <el-input v-model="editGoodsForm.count" type="number"></el-input>
        </el-form-item>

        <el-form-item label="商品邮费" prop="logistics_price">
          <el-input
            v-model="editGoodsForm.logistics_price"
            type="number"
          ></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editGoodsDialog = false"
          >取 消</el-button
        >
        <el-button type="primary" @click="handleUpdateGoods">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改商品详细信息 -->

    <el-dialog
      title="修改商品详细信息"
      :visible.sync="editDetailsDialog"
      @close="handleCloseEditDetails"
      width="80%"
    >
      <Tinymce :height="500" v-model="editDetails.info"></Tinymce>
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="editDetailsDialog = false"
          >取 消</el-button
        >
        <el-button type="primary" @click="handleUpdateDetails">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 修改商品轮播图 -->
    <el-dialog
      title="修改商品轮播图信息"
      :visible.sync="editSwiperDialog"
      @close="handleCloseEditSwiper"
      width="70%"
    >
      <div class="goods-swiper-wrapper">
        <div
          class="image-wrapper"
          v-for="(image, index) in swiperList"
          :key="image.id"
        >
          <div class="close" @click="handleCloseSwiper(image.id, index)">
            <i class="el-icon-circle-close"></i>
          </div>

          <div class="left" @click="handleUpSwiper(image.id, index)">
            <i class="el-icon-caret-left"></i>
          </div>
          <div class="image">
            <img :src="image.url" />
            <div class="image-show" @click="handleShowSwiper(image.url)">
              <span>点击浏览图片</span>
            </div>
          </div>

          <div class="right" @click="handleDownSwiper(image.id, index)">
            <i class="el-icon-caret-right"></i>
          </div>
        </div>
      </div>
      <el-image
        ref="preview"
        style="width: 0; height: 0"
        :src="currSwiper[0]"
        :preview-src-list="currSwiper"
      >
      </el-image>
      <!-- handleUploadSwiper -->
      <span slot="footer" class="dialog-footer">
        <el-upload
          style="display: inline-block; margin-right: 10px"
          multiple
          :show-file-list="false"
          action="#"
          :http-request="handleUploadSwiper"
        >
          <el-button type="primary">点击上传</el-button>
        </el-upload>
        <el-button type="primary" @click="editSwiperDialog = false"
          >退 出</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

<script>
import Tinymce from '../tinymce/TinymceComponent.vue'
export default {
  components: {
    Tinymce
  },
  data() {
    return {
      total: 0,
      // 查询参数
      queryInfo: {
        query: '',
        pageNum: 1,
        pageSize: 3
      },
      queryText: '',
      editGoodsDialog: false,
      editGoodsForm: {
        id: '',
        cover: '',
        name: '',
        description: '',
        count: '',

        logistics_price: ''
      },
      editGoodsFormRules: {
        cover: [
          {
            required: true,
            message: '请添加商品封面',
            trigger: 'blur'
          }
        ],
        name: [
          {
            required: true,
            message: '请输入商品名称',
            trigger: 'blur'
          }
        ],
        description: [
          {
            required: true,
            message: '请输入商品描述',
            trigger: 'blur'
          }
        ],
        count: [
          {
            required: true,
            message: '请输入商品库存',
            trigger: 'blur'
          }
        ]
      },
      goodsList: [],
      currParamList: [],
      paramsFormData: {
        id: '',
        name: '',
        goods_id: '',
        price: '',
        is_empty: false
      },
      paramsFormRules: {
        name: [
          {
            required: true,
            message: '请输入名称',
            trigger: 'blur'
          }
        ],
        goods_id: [
          {
            required: true,
            message: '商品id不能为空',
            trigger: 'blur'
          }
        ],
        price: [
          {
            required: true,
            message: '请输入参数价格',
            trigger: 'blur'
          }
        ]
      },
      paramDialog: false,
      editParamDialog: false,
      isEditParams: false,
      editDetails: {
        goods_id: '',
        info: ''
      },
      editDetailsDialog: false,
      editSwiperDialog: false,
      swiperList: [],
      currSwiper: [''],
      currGoodsId: ''
    }
  },

  created() {
    this.headers = this.$headers
    this.domain = this.$domain
    this.getGoodsList()
  },
  methods: {
    // 根据分页获取对应的商品列表
    async getGoodsList() {
      const { data: res } = await this.$http.get('/getGoodsList', {
        params: this.queryInfo
      })
      if (res.status !== 200) {
        return this.$message.error('获取商品列表失败!')
      }
      // console.log(res)
      this.goodsList = res.data.data
      // console.log(this.goodsList, res.data.data, res)

      this.total = res.data.totalNum
      this.$message.success('获取商品列表成功!')
    },

    async handleUpSwiper(id, index) {
      if (index === 0) {
        return this.$message.info('到头了，不准移动')
      }
      // console.log('上', id, )
      const { data: res } = await this.$http.post('/updateGoodsSwiperIndex', {
        id: id,
        neg_id: this.swiperList[index - 1].id
      })

      if (res.status !== 200) {
        return this.$message.error(res.message)
      }

      // 交换两个的value
      const tempIndex = this.swiperList[index].sort_index
      this.swiperList[index].sort_index = this.swiperList[index - 1].sort_index
      this.swiperList[index - 1].sort_index = tempIndex
      this.swiperList.sort((a, b) => {
        return a.sort_index - b.sort_index
      })
    },
    async handleDownSwiper(id, index) {
      if (index === this.swiperList.length - 1) {
        return this.$message.info('到头了，不准移动')
      }
      const { data: res } = await this.$http.post('/updateGoodsSwiperIndex', {
        id: id,
        neg_id: this.swiperList[index + 1].id
      })
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }

      const tempIndex = this.swiperList[index].sort_index
      this.swiperList[index].sort_index = this.swiperList[index + 1].sort_index
      this.swiperList[index + 1].sort_index = tempIndex

      this.swiperList.sort((a, b) => {
        return a.sort_index - b.sort_index
      })
    },
    handleShowSwiper(url) {
      // console.log(this.$refs.preview, url)
      this.currSwiper[0] = url
      this.$refs.preview.clickHandler()
    },

    async handleCloseSwiper(id, index) {
      let confirm

      try {
        confirm = await this.$confirm('是否参数该轮播图?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      } catch (e) {
        // console.log('取消')
        return
      }
      if (confirm === 'confirm') {
        const { data: res } = await this.$http.post(
          '/deleteGoodsMediaById/' + id
        )

        if (res.status !== 200) {
          this.$message.error(res.message)
          return
        }

        this.swiperList.splice(index, 1)
        this.$message.success(res.message)
      }
    },

    async handlesearchGoods() {
      this.queryInfo.pageNum = 1
      this.getGoodsList()
    },

    async handleUploadSwiper(e) {
      // console.log(this.currGoodsId, e)
      const formData = new FormData()
      formData.append('swiper', e.file)
      formData.append('goodsId', this.currGoodsId)

      const { data: res } = await this.$http.post(
        '/uploadSingleSwiperByGId',
        formData
      )
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }
      this.$message.success(res.message)
      this.getSwiperData(this.currGoodsId)
    },

    async handleUpdateGoods() {
      this.$refs.goodsFormRef.validate(async (valid) => {
        if (!valid) return
        // console.log(this.editGoodsForm)
        const logP =
          this.editGoodsForm.logistics_price === '' ||
          this.editGoodsForm.logistics_price.length === 0
            ? 0
            : this.editGoodsForm.logistics_price

        const formData = new FormData()
        const goodsBase = {
          id: parseInt(this.editGoodsForm.id),
          cover_is_update: this.editGoodsForm.cover.file != null,
          name: this.editGoodsForm.name,
          description: this.editGoodsForm.description,
          count: parseInt(this.editGoodsForm.count),
          logistics_price: logP
        }
        formData.append('goods', JSON.stringify(goodsBase))
        if (this.editGoodsForm.cover.file != null) {
          formData.append('cover', this.editGoodsForm.cover.file)
        }
        const { data: res } = await this.$http.post(
          '/updateGoodsInfo',
          formData
        )
        if (res.status !== 200) {
          return this.$message.error(res.message)
        }

        this.editGoodsDialog = false
        this.$message.success(res.message)
        this.getGoodsList()
      })
    },

    async handleUpdateDetails() {
      if (this.editDetails.info.length === 0 || this.editDetails.info === '') {
        return this.$message.info('商品详细信息不能为空')
      }

      const formData = new FormData()
      const urls = this.extractBlobUrls(this.editDetails.info)
      // console.log(urls)
      // console.log(this.editDetails)

      for (let i = 0; i < urls.length; i++) {
        const file = await this.blobUrlToFile(urls[i], `file${i}.png`)
        formData.append('images[]', file)
      }

      formData.append('details', JSON.stringify(this.editDetails))

      const { data: res } = await this.$http.post(
        '/updateGoodsDetails',
        formData
      )
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }
      this.editDetailsDialog = false

      return this.$message.success(res.message)
    },

    async handleDeleteGoods(id) {
      const confirmRes = await this.$confirm(
        '是否（恢复/删除）该商品信息',
        '提示',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }
      ).catch((err) => err)

      // 如果用户确认删除，返回的是文本confirm
      // 如果用户取消删除，返回的是cancel
      if (confirmRes !== 'confirm') {
        return this.$message.info('已取消删除')
      }

      // 删除

      const { data: res } = await this.$http.post('/deleteGoodsById/' + id)
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }

      this.$message.success(res.message)
      this.getGoodsList()
    },

    handleShowGoodsDialog(goods) {
      // console.log(goods)
      this.editGoodsDialog = true
      this.editGoodsForm = {
        id: goods.id,
        cover: {
          file: null,
          url: goods.cover_url
        },
        name: goods.name,
        description: goods.description,
        count: goods.count,
        logistics_price: goods.logistics_price
      }
    },

    handleShowParamDialog(goodsId) {
      // console.log(goodsId)
      this.getParamData(goodsId)
      this.paramsFormData.goods_id = goodsId
      this.paramDialog = true
    },

    async handleShowDetailsDialog(goodsId) {
      const { data: res } = await this.$http.get('/getGoodsDetails/' + goodsId)
      // console.log(res)
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }
      this.editDetails.goods_id = goodsId
      this.editDetails.info = res.data
      this.editDetailsDialog = true
    },

    async handleShowSwiperDialog(goodsId) {
      this.getSwiperData(goodsId)
      this.editSwiperDialog = true
    },

    async getSwiperData(goodsId) {
      const { data: res } = await this.$http.get('/getGoodsSwiper/' + goodsId)
      // console.log(res)
      if (res.status !== 200) {
        return this.$message.error(res.message)
      }

      this.swiperList = res.data
      this.currGoodsId = goodsId
      this.swiperList.sort((a, b) => {
        return a.sort_index - b.sort_index
      })
    },

    async getParamData(goodsId) {
      const { data: res } = await this.$http.get(
        '/getGoodsParamList/' + goodsId
      )

      if (res.status !== 200) {
        this.$message.error(res.message)
        return
      }

      this.currParamList = res.data
      // console.log(res)
    },

    async handleUpdateParams() {
      // 没有验证表单
      // console.log(this.paramsFormData)
      const { data: res } = await this.$http.post('/updateGoodsParam', {
        id: parseInt(this.paramsFormData.id),
        name: this.paramsFormData.name,
        goods_id: parseInt(this.paramsFormData.goods_id),
        price: parseFloat(this.paramsFormData.price),
        is_empty: this.paramsFormData.is_empty
      })

      if (res.status !== 200) {
        this.$message.error(res.message)
        return
      }

      this.getParamData(this.paramsFormData.goods_id)
      this.$message.success(res.message)
      this.editParamDialog = false
    },

    async handleDeleteParam(id, goodsId) {
      let confirm

      try {
        confirm = await this.$confirm('是否参数该商品参数?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      } catch (e) {
        // console.log('取消')
        return
      }

      // console.log(confirm)

      if (confirm === 'confirm') {
        const { data: res } = await this.$http.post('/deleteGoodsParam/' + id)

        if (res.status !== 200) {
          this.$message.error(res.message)
          return
        }

        this.getParamData(goodsId)
        this.$message.success(res.message)
      }
    },

    handleUploadCover(e) {
      const file = e.file
      // 将图片缓存，然后制作临时url展示
      const url = URL.createObjectURL(file)
      this.editGoodsForm.cover.file = file
      this.editGoodsForm.cover.url = url
    },

    handleShowEditParamDialog(params, flag) {
      // console.log(params)
      if (flag) {
        this.paramsFormData = params
      }
      this.isEditParams = flag
      this.editParamDialog = true
    },

    handleCloseEditParam() {
      this.editParamDialog = false
      this.paramsFormData = {
        id: '',
        name: '',
        goods_id: '',
        price: '',
        is_empty: false
      }
    },

    handleCloseEditGoods() {
      this.editGoodsDialog = false
      this.editGoodsForm = {
        id: '',
        cover: '',
        name: '',
        description: '',
        count: '',
        logistics_price: ''
      }
    },
    handleCloseEditSwiper() {
      this.editSwiperDialog = false
      this.swiperList = []
    },
    handleCloseEditDetails() {
      this.editDetailsDialog = false
      this.editDetails = {
        goods_id: '',
        info: ''
      }
    },

    // 监听 pageSize 改变的事件
    handleSizeChange(newSize) {
      this.queryInfo.pageSize = newSize
      this.getGoodsList()
    },
    // 监听 页码值 改变的事件
    handleCurrentChange(newPage) {
      this.queryInfo.pageNum = newPage
      this.getGoodsList()
    },

    beforeAvatarUpload(file) {
      let typeRight = false
      const isLt2M = file.size / 1024 / 1024 < 1
      switch (file.type) {
        case 'image/png':
        case 'image/jpeg':
          typeRight = true
          break
        default:
          console.log(file.type)
          break
      }

      if (!typeRight) {
        this.$message.error('上传头像图片只能是 JPG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 1MB!')
      }

      return typeRight && isLt2M
    },

    handleFileUpload(file) {
      if (!this.beforeAvatarUpload(file.file)) {
        return
      }
      this.loading = true
      // 调用后端服务器的接口
      this.uploadFile(file.file)
        .then((resp) => {
          this.addForm.full_path = this.domain + resp.path
          this.addForm.picture_path = resp.path
          this.$message.success('图片上传成功')
        })
        .catch((e) => {
          this.$message.error(e.message)
          this.$refs.upload.clearFiles()
        })
    },

    /**
     * 上传文件
     */
    async uploadFile(file) {
      const formData = new FormData()
      formData.append('file', file)
      const { data: res } = await this.$http.post('file/upload', formData)

      if (res.code === 200) {
        return JSON.parse(res.msg)
      }

      return Promise.reject(new Error(res.data.message))
    },

    handleCloseDialog() {
      this.addDialogVisible = false
      this.is_edit = false
      this.addForm = {
        id: '',
        picture_path: '',
        full_path: '',
        title: '',
        price: '',
        count: '',
        user_id: ''
      }
      this.queryText = ''
    },

    handleSelect(e) {
      this.addForm.user_id = e.id
    },

    extractBlobUrls(html) {
      const regex = /<img[^>]*src=["'](blob:[^"'>]*)["'][^>]*>/gi
      const blobUrls = []
      let match

      while ((match = regex.exec(html))) {
        if (match[1]) {
          blobUrls.push(match[1])
        }
      }
      return blobUrls
    },

    async blobUrlToFile(blobUrl, fileName) {
      const response = await fetch(blobUrl)
      const blob = await response.blob()
      return new File([blob], fileName, { type: blob.type })
    }
  }
}
</script>

<style lang="less" scoped>
.tox {
  z-index: 9999 !important;
}

.goods-swiper-wrapper {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 20px;

  .image-wrapper {
    cursor: pointer;
    display: inline-flex;
    width: 100%;
    height: 225px;
    position: relative;
    overflow: hidden;

    .close {
      width: 35px;
      height: 35px;
      // background-color: #8c939d;
      display: flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      top: 0;
      right: 0;
      font-size: 30px;
      color: #fff;
      z-index: 20;
    }

    .close:hover {
      color: #409eff;
    }

    .image-show,
    .left,
    .right {
      transition: all 0.5s ease-in-out;
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      background-color: rgba(0, 0, 0, 0.3);
      color: #fff;
      opacity: 0;
      * {
        pointer-events: none;
      }
    }
    .left,
    .right {
      font-size: 50px;
      position: absolute;
      width: 30%;
      height: 100%;
      top: 0%;
      z-index: 10;
    }
    .left {
      left: -30%;
    }
    .right {
      right: -30%;
    }
    .image {
      // pointer-events: all;
      width: 100%;
      height: 100%;
      img {
        width: 100%;
        height: 100%;
      }
    }
    .image-show {
      position: absolute;
      top: 0%;
      font-size: 20px;
      left: 30%;
      width: 40%;
      z-index: 10;
      height: 100%;
      pointer-events: all;
      writing-mode: vertical-rl;
      text-orientation: upright;
    }
  }

  .image-wrapper:hover {
    .left {
      left: 0%;
      opacity: 1;
    }
    .right {
      right: 0;
      opacity: 1;
    }
    .image-show {
      opacity: 1;
    }
  }
}

.param-wrapper {
  width: 100%;
  max-height: 50vh;
  padding: 10px;
  box-sizing: border-box;
  justify-content: flex-start;
  align-items: center;
  display: flex;
  flex-direction: column;
  overflow-y: auto;

  :deep(.el-tag) {
    margin-top: 10px;
  }
}

.avatar-uploader :deep(.el-upload) {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader :deep(.el-upload):hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 100px;
  height: 100px;
  line-height: 100px;
  text-align: center;
}
.avatar {
  width: 100px;
  height: 100px;
  display: block;
}

.tips {
  color: red;
}
</style>
